package com.baicaoyuan.web.common.relation;

import com.baicaoyuan.web.common.PlatformIdConfig;
import com.baicaoyuan.web.model.UserDO;
import com.baicaoyuan.web.service.UserService;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Data
@Service
public class RelationCache {

    private long maximumSize = 10000;
    private List<node> allNode;

    public Map<Long, List<node>> mapUserToChild;


    @Autowired
    private UserService userService;

    @Autowired
    PlatformIdConfig platformIdConfig;

    private Cache<Long, UserDO> cache = CacheBuilder.newBuilder()
            .maximumSize(maximumSize)
            .concurrencyLevel(Runtime.getRuntime().availableProcessors())
            .recordStats()
            .build();

    @PostConstruct
    public void loadCache() {
        List<UserDO> users = userService.findByStatusAndType();
        users.forEach(x -> cache.put(x.getId(), x));
        reload();
    }

    public void add(Long userId) {
        UserDO userDO = userService.findOne(userId);
        if (userDO != null && userDO.getType() != null && userDO.getStatus() != null &&
                1 == userDO.getType() && "1".equals(userDO.getStatus())) {
            cache.put(userDO.getId(), userDO);
            reload();
        }
    }

    public void delete(Long userId) {
        Objects.requireNonNull(userId);
        cache.invalidate(userId);
        reload();
    }

    /**
     * 加载用户数据
     */
    public void reload() {
        allNode = Lists.newArrayList();
        cache.asMap().forEach(
                (userId, u) -> {
                    allNode.add(new node(u.getId(), u.getUserDirectId()));
                }
        );
        loadLeaderTeam();
    }

    //加载团长树
    private void loadLeaderTeam() {
        if (allNode != null) {
            mapUserToChild = new HashMap<>();
            UserNodeRecursion userNodeRecursion = new UserNodeRecursion();
            allNode.forEach(x -> {
                //是否为团长
                if (checkTeamLeader(x.id)) {
                    mapUserToChild.put(x.id, userNodeRecursion.treeUnderPid(allNode, x.getId()));
                }
            });
        }
    }

    /**
     * 定位团长
     * 一颗树上，加入一个用户，则判断该树上满足团长要求的用户。若存在，则设置团长标识
     * 10个直邀客户 , 共50个子客户， 可配置
     *
     * @return
     */
    public boolean checkTeamLeader(Long userId) {
        UserNodeRecursion userNodeRecursion = new UserNodeRecursion();
        Integer j = userNodeRecursion.treeUnderPidDirect(allNode, userId).size();
        boolean d = j >= platformIdConfig.getLeader_direct();
        Integer count = userNodeRecursion.treeUnderPid(allNode, userId).size();
        boolean i = count >= platformIdConfig.getLeader_all();
        return d && i;
    }


    /**
     * 获取包含该jzz用户的团长， 分润使用
     */
    public List<Long> queryTeamLeaderContainsJzzUser(Long userId) {
        List<Long> result = Lists.newArrayList();
        mapUserToChild.forEach((key, children) -> {
            for (node u : children) {
                if (u.getId() == userId) {
                    result.add(key);
                    break;
                }
            }
        });
        return result;
    }

    public List<Long> getTeamLeader() {
        reload();
        return Lists.newArrayList(mapUserToChild.keySet());
    }

    @Data
    @AllArgsConstructor
    class node {
        private Long id;
        private Long pid;
    }
}